Categories
Gatsby.js

Gatsby.js — Pagination

Spread the love

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Pagination

We can add pagination for our pages with Gatsby.

To do this, we write:

gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-transformer-remark`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `content`,
        path: `${__dirname}/src/content`,
      },
    },
  ],
}

gatsby-node.js

const path = require("path")
const { createFilePath } = require("gatsby-source-filesystem")
exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions
  const result = await graphql(
    `
      {
        allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: DESC }
          limit: 1000
        ) {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
      }
    `
  )
  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

const posts = result.data.allMarkdownRemark.edges
  const postsPerPage = 6
  const numPages = Math.ceil(posts.length / postsPerPage)
  Array.from({ length: numPages }).forEach((_, i) => {
    createPage({
      path: i === 0 ? `/blog` : `/blog/${i + 1}`,
      component: path.resolve("./src/templates/blog-list-template.js"),
      context: {
        limit: postsPerPage,
        skip: i * postsPerPage,
        numPages,
        currentPage: i + 1,
      },
    })
  })
}
exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
  }
}

src/templates/blog-list-template.js

import React from "react"
import { graphql } from "gatsby"

export default class BlogList extends React.Component {
  render() {
    const posts = this.props.data.allMarkdownRemark.edges
    return (
      <div>
        {posts.map(({ node }) => {
          const title = node.frontmatter.title || node.fields.slug
          return <div key={node.fields.slug}>{title}</div>
        })}
      </div>
    )
  }
}
export const blogListQuery = graphql`
  query blogListQuery($skip: Int!, $limit: Int!) {
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      limit: $limit
      skip: $skip
    ) {
      edges {
        node {
          fields {
            slug
          }
          frontmatter {
            title
          }
        }
      }
    }
  }
`

We add the gatsby-source-filesystem plugin to read Markdown files from the file system.

Then we use the gatsby-transformer-remark plugin to parse the Markdown file into HTML.

The gatsby-node.js file gets the Markdown posts with a GraphQL query.

Then create an array with the length being the number of pages.

Then we loop through them with forEach and call createPage in the callback to pass in the path to the blog-list-template file along with other data in the context.

The context property has more data that we pass into the blog-list-template file.

They include the postsPerPage , the number of items to skip, numPages which is the number of pages, and the currentPage .

In the blog-list-template.js file, we make the blogListQuery with the skip and limit parameters to get the items from a given page.

In the BlogList component, we call map on posts to render the post title.

We read the Markdown files from the src/content folder.

Then when we go to http://localhost:8000/blog, we see the first page.

http://localhost:8000/blog has the 2nd page and so on.

Conclusion

We can add pagination easily with Gatsby.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *